import { CancelExecutor, CancelTokenSource, Canceler } from '../types'
import Cancel from './Cancel'

interface ResolvedPromise {
  // (reason: string): void
  (reason: Cancel): void
}

export default class CancelToken {
  /* promise: Promise<string>
  reason?: string */
  promise: Promise<Cancel>
  reason?: Cancel

  constructor(executor: CancelExecutor) {
    let resolvedPromise: ResolvedPromise

    /* this.promise = new Promise<string>(resolve => {
      resolvedPromise = resolve
    }) */
    this.promise = new Promise<Cancel>(resolve => {
      resolvedPromise = resolve
    })

    executor(message => {
      if (this.reason) {
        return
      }
      // this.reason = message
      this.reason = new Cancel(message)
      resolvedPromise(this.reason!)
    })
  }

  throwIfRequested() {
    if (this.reason) {
      throw this.reason
    }
  }

  static source(): CancelTokenSource {
    let cancel!: Canceler
    const token = new CancelToken(c => {
      cancel = c
    })

    return { cancel, token }
  }
}
